package com.atguigu.spzx.order.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.atguigu.spzx.cart.client.CartClient;
import com.atguigu.spzx.common.exception.SpzxException;
import com.atguigu.spzx.common.interceptor.SpzxUserInfoInterceptor;
import com.atguigu.spzx.model.dto.order.OrderSubmitDto;
import com.atguigu.spzx.model.entity.h5.CartItem;
import com.atguigu.spzx.model.entity.h5.UserInfo;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import com.atguigu.spzx.model.entity.order.OrderItem;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.entity.user.UserAddress;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.order.OrderTradeVo;
import com.atguigu.spzx.order.mapper.OrderInfoMapper;
import com.atguigu.spzx.order.mapper.OrderItemMapper;
import com.atguigu.spzx.order.service.OrderInfoService;
import com.atguigu.spzx.product.client.ProductClient;
import com.atguigu.spzx.user.client.UserClient;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class OrderInfoServiceImpl implements OrderInfoService {
    @Resource
    CartClient cartClient;
    @Resource
    ProductClient productClient;
    @Resource
    UserClient userClient;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    OrderInfoMapper orderInfoMapper;
    @Resource
    OrderItemMapper orderItemMapper;
    @Override
    public OrderTradeVo trade() {
        //1、查询当前用户已选中的购物项
        Long userId = SpzxUserInfoInterceptor.THREAD_LOCAL.get().getId();
        //远程访问购物车模块查询已选中的购物项
        Result<List<CartItem>> result = cartClient.findCheckedCartItems();
        if(result.getCode().intValue()!=200){
            throw new SpzxException(ResultCodeEnum.ERROR , null);
        }

        List<CartItem> cartItems = result.getData();
        if(CollectionUtils.isEmpty(cartItems)){
            throw new SpzxException(ResultCodeEnum.ORDER_TRADE_ERROR , null);
        }

        OrderTradeVo orderTradeVo = new OrderTradeVo();
        //需要保证id生成时全局唯一：
        long orderId = IdUtil.createSnowflake(1, 1).nextId();
        //缓存orderId
        stringRedisTemplate.opsForValue().set(String.valueOf(orderId) , "1" ,
                20 , TimeUnit.MINUTES);
        // 一个购物项 对应一个 orderItem: 将购物项集合转为orderItem集合
        List<OrderItem> orderItemList = cartItems.stream().map(cartItem -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setSkuId(cartItem.getSkuId());
            orderItem.setSkuName(cartItem.getSkuName());
            orderItem.setThumbImg(cartItem.getImgUrl());
            orderItem.setOrderId(orderId);
            // 存在价格同步问题？？
            orderItem.setSkuPrice(cartItem.getCartPrice());
            orderItem.setSkuNum(cartItem.getSkuNum());
            return orderItem;
        }).collect(Collectors.toList());

        orderTradeVo.setOrderItemList(orderItemList);
        //累加每个orderItem的总金额
        //  先对每个orderItem进行计算  得到单个商品的总价(  price*skuNum )
        BigDecimal totalAmount = orderItemList.stream()
                //获取每个orderItem的单价*数量计算 单品总价后返回
                .map(orderItem -> orderItem.getSkuPrice()
                        .multiply(new BigDecimal(orderItem.getSkuNum()))
                )
                //前面的计算得到了所有单品的总价 集合  ，遍历所有的单品总价  每两个单品总价累加
                .reduce((a, b) -> a.add(b))
                .get();//获取前面累加的结果
        orderTradeVo.setTotalAmount(totalAmount);
        orderTradeVo.setPrice(totalAmount);
        return orderTradeVo;
    }

    @Override
    public Long submitOrder(OrderSubmitDto orderSubmitDto) {
        //1、幂等性判断：
        OrderItem orderItem = orderSubmitDto.getOrderItemList().get(0);
        //数值型长度超过16位后，前端 或者  后端jackson会对后面的进行四舍五入处理
        Long orderId = orderItem.getOrderId();
        Boolean hasKey = stringRedisTemplate.hasKey(String.valueOf(orderId));
        if(!hasKey){
            throw new SpzxException(ResultCodeEnum.ORDER_SUBMIT_ERROR ,null);
        }
        //删除使用过的orderId缓存
        stringRedisTemplate.delete(String.valueOf(orderId));
        //2、判断库存是否足够： 不考虑减库存、支付后修改订单状态时 修改库存
        List<OrderItem> orderItems = orderSubmitDto.getOrderItemList();
        orderItems.forEach(item->{
            Result<ProductSku> result = productClient.findSkuById(item.getSkuId());
            if(result.getCode()!=200 || result.getData().getStockNum().intValue()<item.getSkuNum().intValue()){
                throw new SpzxException(ResultCodeEnum.SKU_STOCK_ERROR,null);
            }
            //校验商品价格
            if( result.getData().getSalePrice().compareTo(item.getSkuPrice())!=0){
                throw new SpzxException(ResultCodeEnum.SKU_STOCK_ERROR,null);
            }
        });
        //3、保存订单到order_info
        UserInfo userInfo = SpzxUserInfoInterceptor.THREAD_LOCAL.get();
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userInfo.getId());
        orderInfo.setNickName(userInfo.getNickName());
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        orderInfo.setOrderNo(snowflake.nextIdStr());
//        orderInfo.setCouponId()
        BigDecimal totalAmount = orderItems.stream().map(item -> item.getSkuPrice()
                        .multiply(new BigDecimal(item.getSkuNum())))
                .reduce((a, b) -> a.add(b)).get();
        orderInfo.setTotalAmount(totalAmount);
        orderInfo.setCouponAmount(new BigDecimal(0));
        orderInfo.setOriginalTotalAmount(totalAmount);
        orderInfo.setFeightFee(orderSubmitDto.getFeightFee());
        orderInfo.setOrderStatus(0);//0代表待支付
        orderInfo.setRemark(orderSubmitDto.getRemark());
        //user服务：根据地址id查询地址详情
        Result<UserAddress> result = userClient.getUserAddress(orderSubmitDto.getUserAddressId());
        if(result.getCode()!=200){
            throw new SpzxException(ResultCodeEnum.ERROR , null);
        }
        UserAddress address = result.getData();
        orderInfo.setReceiverName(address.getName());//
        orderInfo.setReceiverPhone(address.getPhone());
        orderInfo.setReceiverTagName(address.getTagName());
        orderInfo.setReceiverProvince(address.getProvinceCode());
        orderInfo.setReceiverCity(address.getCityCode());
        orderInfo.setReceiverDistrict(address.getDistrictCode());
        orderInfo.setReceiverAddress(address.getAddress());
        orderInfoMapper.save(orderInfo);
        //4、保存orderItem列表
        //绑定orderItem和orderInfo
        orderItems.forEach(item->{
            item.setOrderId(orderInfo.getId());
        });
        orderItemMapper.batchSave(orderItems);

        //5、删除购物车中本次订单使用过的购物项
        cartClient.deleteCartItems();

        return orderInfo.getId();
    }

    @Override
    public OrderInfo findOrderById(Long id) {
        return orderInfoMapper.findOrderById(id);
    }

    @Override
    public OrderTradeVo buy(Long skuId) {
        OrderTradeVo orderTradeVo = new OrderTradeVo();
        //需要保证id生成时全局唯一：
        long orderId = IdUtil.createSnowflake(1, 1).nextId();
        //缓存orderId
        stringRedisTemplate.opsForValue().set(String.valueOf(orderId) , "1" ,
                20 , TimeUnit.MINUTES);
        // 查询skuId对应的sku数据
        ProductSku sku = productClient.findSkuById(skuId).getData();
        OrderItem orderItem = new OrderItem();
        orderItem.setSkuId(skuId);
        orderItem.setSkuName(sku.getSkuName());
        orderItem.setThumbImg(sku.getThumbImg());
        orderItem.setOrderId(orderId);
        // 存在价格同步问题？？
        orderItem.setSkuPrice(sku.getSalePrice());
        orderItem.setSkuNum(1);
        orderTradeVo.setOrderItemList(Arrays.asList(orderItem));
        //累加每个orderItem的总金额
        //  先对每个orderItem进行计算  得到单个商品的总价(  price*skuNum )
        BigDecimal totalAmount = sku.getSalePrice();
        orderTradeVo.setTotalAmount(totalAmount);
        orderTradeVo.setPrice(totalAmount);
        return orderTradeVo;

    }

    @Override
    public PageInfo<OrderInfo> page(Integer page, Integer limit, Integer orderStatus) {
        PageHelper.startPage(page,limit);
        Long userId = SpzxUserInfoInterceptor.THREAD_LOCAL.get().getId();
        List<OrderInfo>  list = orderInfoMapper.findPageByStatus(orderStatus,userId);
        PageInfo<OrderInfo> pageInfo = new PageInfo<>(list);
        list.forEach(orderInfo -> {
            //查询orderInfo的订单项列表
            List<OrderItem> orderItems =  orderItemMapper.findOrderItemsByOrderId(orderInfo.getId());
            orderInfo.setOrderItemList(orderItems);
        });
        return pageInfo;
    }

    @Override
    public OrderInfo findOrderByOrderNo(Long orderNo) {
        return orderInfoMapper.findOrderByOrderNo(orderNo);

    }

    @Override
    public void updateOrderPayStatus(String orderNo) {
        orderInfoMapper.updateOrderPayStatus(orderNo);
    }
}
//将orderItem转为校验库存的对象集合
//  skuId   skuNum   status: 验库存的状态